import cv2 import numpy as np import os import subprocess import sys from tkinter import Tk, filedialog, simpledialog def effect_cartoon(frame): color = frame for _ in range(2): color = cv2.bilateralFilter(color, 9, 150, 150) gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) gray = cv2.medianBlur(gray, 7) edges = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 2) edges = cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR) return cv2.bitwise_and(color, edges) def effect_stylize(frame): try: return cv2.stylization(frame, sigma_s=60, sigma_r=0.5) except Exception: return frame def effect_detail(frame): return cv2.detailEnhance(frame, sigma_s=10, sigma_r=0.15) def effect_pencil(frame): _, color = cv2.pencilSketch(frame, sigma_s=60, sigma_r=0.07, shade_factor=0.05) return color def effect_oilpaint(frame): if hasattr(cv2, "xphoto") and hasattr(cv2.xphoto, "oilPainting"): return cv2.xphoto.oilPainting(frame, 10, 1) return frame def effect_edge(frame): gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) edges = cv2.Canny(gray, 100, 200) edges = cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR) return cv2.addWeighted(frame, 0.6, edges, 0.4, 0) def effect_glow(frame): blur = cv2.GaussianBlur(frame, (0, 0), 15) return cv2.addWeighted(frame, 1.5, blur, -0.5, 0) def effect_pixel(frame): h, w = frame.shape[:2] size = max(4, w // 100) temp = cv2.resize(frame, (w // size, h // size), interpolation=cv2.INTER_LINEAR) return cv2.resize(temp, (w, h), interpolation=cv2.INTER_NEAREST) def effect_glitch(frame): h, w = frame.shape[:2] shift = np.random.randint(-10, 10) b, g, r = cv2.split(frame) b = np.roll(b, shift, axis=1) g = np.roll(g, -shift, axis=0) r = np.roll(r, shift // 2, axis=1) return cv2.merge([b, g, r]) def effect_hsv(frame): hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) hsv[:, :, 0] = (hsv[:, :, 0] + 60) % 180 return cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR) def effect_toon3d(frame): base = cv2.bilateralFilter(frame, 9, 150, 150) levels = 8 step = 256 // levels quant = (base // step) * step gray = cv2.cvtColor(base, cv2.COLOR_BGR2GRAY) gray_blur = cv2.medianBlur(gray, 7) edges = cv2.adaptiveThreshold(gray_blur, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 2) gx = cv2.Sobel(gray_blur, cv2.CV_32F, 1, 0, ksize=3) gy = cv2.Sobel(gray_blur, cv2.CV_32F, 0, 1, ksize=3) nx = -gx ny = -gy nz = np.ones_like(gx) norm = np.maximum(np.sqrt(nx * nx + ny * ny + nz * nz), 1e-6) nx /= norm ny /= norm nz /= norm L = np.array([0.4, -0.4, 0.8], dtype=np.float32) L = L / np.linalg.norm(L) shade = np.clip(nx * L[0] + ny * L[1] + nz * L[2], 0, 1) shade = cv2.GaussianBlur(shade, (0, 0), 1.0) shaded = (quant.astype(np.float32) * shade[..., None]).clip(0, 255).astype(np.uint8) edges_bgr = cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR) return cv2.bitwise_and(shaded, edges_bgr) effects = { "cartoon": effect_cartoon, "stylize": effect_stylize, "detail": effect_detail, "pencil": effect_pencil, "oilpaint": effect_oilpaint, "edge": effect_edge, "glow": effect_glow, "pixel": effect_pixel, "glitch": effect_glitch, "hsv": effect_hsv, "toon3d": effect_toon3d } Tk().withdraw() input_path = filedialog.askopenfilename(title="Choisir une vidéo .mp4", filetypes=[("Vidéos", "*.mp4")]) if not input_path: sys.exit("Aucune vidéo choisie.") output_path = filedialog.asksaveasfilename(defaultextension=".mp4", filetypes=[("Vidéos", "*.mp4")], title="Enregistrer la vidéo transformée sous...") if not output_path: sys.exit("Aucun fichier de sortie choisi.") effect_name = simpledialog.askstring("Effet", "Choisis un effet :\n" + ", ".join(effects.keys())) if not effect_name or effect_name not in effects: sys.exit("Effet inconnu.") fx = effects[effect_name] cap = cv2.VideoCapture(input_path) fps = cap.get(cv2.CAP_PROP_FPS) if fps <= 0: fps = 25.0 w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) fourcc = cv2.VideoWriter_fourcc(*"mp4v") out = cv2.VideoWriter(output_path, fourcc, fps, (w, h)) if not out.isOpened(): sys.exit("Erreur de création du fichier de sortie.") print("Transformation en cours...") total = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) count = 0 while True: ret, frame = cap.read() if not ret: break proc = fx(frame) out.write(proc) count += 1 if total > 0 and count % 30 == 0: print(f"{int(100 * count / total)}%") cap.release() out.release() print("✅ Vidéo créée avec succès :", output_path)